/**   
* @Title: WebInterceptor.java
* @Package org.xaoyaoyao.cloud.web.interceptor
* @Description: TODO
* @author xaoyaoyao
* @date Feb 11, 2019 2:31:24 PM
* @version V1.0   
*/
package org.xaoyaoyao.cloud.web.interceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.core.NamedThreadLocal;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import lombok.extern.slf4j.Slf4j;

/**
* @ClassName: WebInterceptor
* @Description: TODO
* @author xaoyaoyao
* @date Feb 11, 2019 2:31:24 PM
* 
*/
/**
 * @ClassName: WebInterceptor
 * @Description: 拦截器 1、日志记录：记录请求信息的日志，以便进行信息监控、信息统计、计算PV（Page View）等。
 *               2、权限检查：如登录检测，进入处理器检测检测是否登录，如果没有直接返回到登录页面；
 *               3、性能监控：有时候系统在某段时间莫名其妙的慢，可以通过拦截器在进入处理器之前记录开始时间，在处理完后记录结束时间，从而得到该请求的处理时间（如果有反向代理，如apache可以自动记录）；
 *               4、通用行为：读取cookie得到用户信息并将用户对象放入请求，从而方便后续流程使用，还有如提取Locale、Theme信息等，只要是多个处理器都需要的即可使用拦截器实现。
 *               5、OpenSessionInView：如Hibernate，在进入处理器打开Session，在完成后关闭Session。
 *               本质也是AOP（面向切面编程），也就是说符合横切关注点的所有功能都可以放入拦截器实现。
 * @author xaoyaoyao
 * @date 2018年9月26日 上午11:36:46
 * 
 */
@Slf4j
public class WebInterceptor implements HandlerInterceptor {

	/**
	 * 在业务处理器请求前被调用,在该方法中对用户请求request进行处理。 若
	 * 决定改拦截器对请求进行拦截处理后还需要调用其它的拦截器，或者业务处理器去进行处理则返回 true， 否则返回false
	 * 
	 */
	private NamedThreadLocal<Long> startTimeThreadLocal = new NamedThreadLocal<Long>("StopWatch-StartTime");

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
		log.info(">>>>>>>> 请求: {} 开始处理", request.getRequestURI());
		long beginTime = System.currentTimeMillis();// 1、开始时间
		startTimeThreadLocal.set(beginTime);// 线程绑定变量（该数据只有当前请求的线程可见）
		return true;
	}

	/**
	 * 在业务处理器处理完请求后，但是DispatcherServlet向客户端返回响应前被调用。 在该方法中对用户请求的request进行处理。
	 */
	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
		log.info(">>>>>>>> 请求: {} 正在处理", request.getRequestURI());
	}

	/**
	 * 在DispatherServlet完全处理完请求后调用，可以在该方法中进行一些资源请里的操作
	 */
	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
		log.info(">>>>>>>> ControllerInterceptor-afterCompletion 结束");
		long endTime = System.currentTimeMillis();// 2、结束时间
		long beginTime = startTimeThreadLocal.get();// 得到线程绑定的局部变量（开始时间）
		long consumeTime = endTime - beginTime;// 3、消耗的时间
		log.info(String.format(">>>>>>>> 请求: %s 耗时: %d millis", request.getRequestURI(), consumeTime));
	}

}

